package com.smugmugsoftware.airconcalc.advanced;

import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;

import android.support.v4.app.Fragment;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.CheckBox;

public class AdvancedCalculatorActivity extends FragmentActivity implements MainActivityInterface {

	Fragment activeFragment;
	DialogFragment dialogFragment;

	NewRoomFragmentInterface newRoomFragment;
	RoomListFragmentInterface roomListFragment;
	LocaleFragmentInterface localeFragment;

	public NumberFormat nf;
	public DecimalFormatSymbols dfs;
	public DecimalFormat df;

	Building thisBuilding;

	public AdvancedCalculatorActivity() {}

	@Override
	protected void onCreate(Bundle b) {
		super.onCreate(b);

		if (b != null && b.getParcelable("BUILDING") != null) {
			thisBuilding = b.getParcelable("BUILDING");
		} else {
			thisBuilding = readFile();
		}

		nf = NumberFormat.getInstance(Locale.getDefault()); 
		dfs = new DecimalFormatSymbols(Locale.getDefault());
		df = new DecimalFormat();

		setContentView(R.layout.advanced_calc_main);
		
		SharedPreferences prefs = getSharedPreferences("config.dat", Context.MODE_PRIVATE);
		if (prefs.getBoolean("FIRST_RUN", true)) {
			displayInfoDialog(this, InformationDialog.FIRST_RUN, "FIRST_RUN");
		} else {
			displayInfoDialog(this, InformationDialog.BETA_WARNING, null);
		}
		
		if (b != null && getSupportFragmentManager().getFragment(b, "ACTIVE_FRAGMENT") != null) {

			try {

				Fragment fragment = getSupportFragmentManager().getFragment(b, "ACTIVE_FRAGMENT");
				if (fragment instanceof AdvancedNewRoomFragment) {
					newRoomFragment = (NewRoomFragmentInterface) fragment;
				}

				if (fragment instanceof AdvancedRoomListFragment) {
					roomListFragment = (RoomListFragmentInterface) fragment;
				}

				if (fragment instanceof AdvancedLocaleFragment) {
					localeFragment = (AdvancedLocaleFragment) fragment;
				}

				FragmentTransaction transaction = getSupportFragmentManager().beginTransaction().replace(R.id.mainView, fragment);
				transaction.commit();

			} catch (Exception e) {

				e.printStackTrace();

				AdvancedRoomListFragment listFragment = new AdvancedRoomListFragment(thisBuilding);
				roomListFragment = (RoomListFragmentInterface) listFragment;
				getSupportFragmentManager().beginTransaction().replace(R.id.mainView, listFragment).commit();
			}

		} else {
			AdvancedRoomListFragment listFragment = new AdvancedRoomListFragment(thisBuilding);
			roomListFragment = (RoomListFragmentInterface) listFragment;
			getSupportFragmentManager().beginTransaction().replace(R.id.mainView, listFragment).commit();
		}

		if (b != null && getSupportFragmentManager().getFragment(b, "Dialog") != null) {
			try {
				DialogFragment dialog = (DialogFragment) getSupportFragmentManager().getFragment(b, "Dialog");
				dialog.show(getSupportFragmentManager(), "Dialog");
			} catch (Exception e) { e.printStackTrace(); }
		}
	}
	
	@Override
	public void onAttachFragment(android.support.v4.app.Fragment fragment) {
		super.onAttachFragment(fragment);

		if (!(fragment instanceof DialogFragment)) {
			activeFragment = fragment;
		} else {
			dialogFragment = (DialogFragment) fragment;
		}
	}

	public void displayConstNoDialog(Context c, String[] s) {
		DialogFragment constWizard = new ConstNoWizardDialog(c, s);
		constWizard.show(getSupportFragmentManager(), "Dialog");
	}

	public void getStringFromDialog(int which, String s) {
		dialogFragment = null;

		if (newRoomFragment != null) {
			newRoomFragment.setEditText(which, s);
		}
	}

	public void getDoubleFromDialog(int which, double d) {
		dialogFragment = null;

		if (newRoomFragment != null) {
			newRoomFragment.setEditText(which, d);
		}
	}

	public void getDataFromDialog(int which, double[] d, int facing) {
		dialogFragment = null;

		if (newRoomFragment != null) {
			newRoomFragment.setEditText(which, d, facing);
		}
	}

	public void displayAreaWizardDialog(Context c, int type) {

		DialogFragment constWizard = new AreaWizardDialog(c, type);
		constWizard.show(getSupportFragmentManager(), "Dialog");
	}

	public void displayAreaWizardDialog(Context c, int type, int subType, int[] data) {

		DialogFragment constWizard = new AreaWizardDialog(c, type, subType, thisBuilding.getLatitude(), data);
		constWizard.show(getSupportFragmentManager(), "Dialog");
	}

	public void displaySensibleLoadDialog(Context c, int type) {
		DialogFragment loadWizard = new SensibleLoadDialog(c, type);
		loadWizard.show(getSupportFragmentManager(), "Dialog");
	}

	public void shadeAreaError() {
		dialogFragment = null;

		if (newRoomFragment != null) {
			newRoomFragment.shadeAreaError();
		}
	}

	public void getDataFromDialog(int which, double[] d) {
		dialogFragment = null;

		if (newRoomFragment != null) {
			newRoomFragment.setEditText(which, d);
		}
	}

	public void getDataFromDialog(int which, double[] d, String[] returnList) {
		dialogFragment = null;

		if (which == NewRoomFragmentInterface.LOCALE_DIALOG) {
			if (localeFragment != null) {
				localeFragment.getLocaleData(d, returnList);
			}
		} else if (newRoomFragment != null) {
			newRoomFragment.setEditText(which, d, returnList);
		}		
	}

	public void displaySensibleLoadDialog(Context context, int type, String subType) {
		DialogFragment loadWizard = new SensibleLoadDialog(context, type, subType);
		loadWizard.show(getSupportFragmentManager(), "Dialog");
	}

	public void displaySensibleLoadDialog(Context context, int type, String[] array) {
		DialogFragment loadWizard = new SensibleLoadDialog(context, type, array);
		loadWizard.show(getSupportFragmentManager(), "Dialog");
	}

	public void displayConfirmDialog(Context context, int dialogType, int type, long id) {
		DialogFragment confirmDialog = new ConfirmDialog(context, dialogType, type, id);
		confirmDialog.show(getSupportFragmentManager(), "Dialog");
	}

	@Override
	public void onBackPressed() {
		if (activeFragment instanceof AdvancedNewRoomFragment && newRoomFragment != null) {
			newRoomFragment.cancelScreen();
		} else if (activeFragment instanceof AdvancedLocaleFragment && localeFragment != null) {
			localeFragment.cancelScreen();
		} else {
			super.onBackPressed();
		}
	}

	public void returnFromConfirmDialog(int dialogType, int type, long id) {
		dialogFragment = null;

		if (type == AdvancedRoomListFragment.ROOM_LIST) {
			roomListFragment.returnFromConfirmDialog(dialogType, type, id);
		} else if (type == AdvancedRoomListFragment.LOCALE_EDITOR) {
			localeFragment.returnFromConfirmDialog(dialogType, type, id);
		} else {
			newRoomFragment.returnFromConfirmDialog(dialogType, type, id);
		}
	}

	public void openRoomEditor(long i, Building building) {

		this.thisBuilding = building;

		AdvancedNewRoomFragment roomFragment = null;
		if (i == 1000) {
			roomFragment = new AdvancedNewRoomFragment(thisBuilding.getNewRoom());
		} else {
			roomFragment = new AdvancedNewRoomFragment(thisBuilding.getRooms().get((int) i));
		}

		newRoomFragment = (NewRoomFragmentInterface) roomFragment;
		FragmentTransaction transaction = getSupportFragmentManager().beginTransaction().replace(R.id.mainView, roomFragment);
		transaction.addToBackStack("Window");
		transaction.commit();
	}

	public void openLocaleEditor(Building building) {

		this.thisBuilding = building;

		AdvancedLocaleFragment newLocaleFragment = new AdvancedLocaleFragment(thisBuilding);

		localeFragment = (LocaleFragmentInterface) newLocaleFragment;
		FragmentTransaction transaction = getSupportFragmentManager().beginTransaction().replace(R.id.mainView, newLocaleFragment);
		transaction.addToBackStack("Window");
		transaction.commit();
	}

	public void openReport(Building building) {
		this.thisBuilding = building;

		AdvancedReportFragment newReportFragment = new AdvancedReportFragment(thisBuilding);
		FragmentTransaction transaction = getSupportFragmentManager().beginTransaction().replace(R.id.mainView, newReportFragment);
		transaction.addToBackStack("Window");
		transaction.commit();
	}

	public void openChart(Building building) {
		this.thisBuilding = building;

		AdvancedChartFragment newChartFragment = new AdvancedChartFragment(thisBuilding);
		FragmentTransaction transaction = getSupportFragmentManager().beginTransaction().replace(R.id.mainView, newChartFragment);
		transaction.addToBackStack("Window");
		transaction.commit();
	}

	public void closeRoomEditor(Room room) {

		if (room != null) {
			room.setBTUString("CALC");
			thisBuilding.addRoom(room);
		}

		if (getWindow().getCurrentFocus() != null) {
			InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
			imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0);
		}

		getSupportFragmentManager().popBackStackImmediate();
		getSupportFragmentManager().popBackStackImmediate();

		AdvancedRoomListFragment listFragment = new AdvancedRoomListFragment(thisBuilding);
		roomListFragment = (RoomListFragmentInterface) listFragment;
		FragmentTransaction transaction = getSupportFragmentManager().beginTransaction().replace(R.id.mainView, listFragment);
		transaction.commit();
	}

	public void closeReport() {

		if (getWindow().getCurrentFocus() != null) {
			InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
			imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0);
		}

		getSupportFragmentManager().popBackStackImmediate();
		getSupportFragmentManager().popBackStackImmediate();

		AdvancedRoomListFragment listFragment = new AdvancedRoomListFragment(thisBuilding);
		roomListFragment = (RoomListFragmentInterface) listFragment;
		FragmentTransaction transaction = getSupportFragmentManager().beginTransaction().replace(R.id.mainView, listFragment);
		transaction.commit();
	}

	public void closeChart() {

		if (getWindow().getCurrentFocus() != null) {
			InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
			imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0);
		}

		getSupportFragmentManager().popBackStackImmediate();
		getSupportFragmentManager().popBackStackImmediate();

		AdvancedRoomListFragment listFragment = new AdvancedRoomListFragment(thisBuilding);
		roomListFragment = (RoomListFragmentInterface) listFragment;
		FragmentTransaction transaction = getSupportFragmentManager().beginTransaction().replace(R.id.mainView, listFragment);
		transaction.commit();
	}

	public void closeLocaleEditor(Building building) {

		if (building != null) {
			thisBuilding = building;
		}
		
		if (getWindow().getCurrentFocus() != null) {
			InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
			imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0);
		}

		getSupportFragmentManager().popBackStackImmediate();
		getSupportFragmentManager().popBackStackImmediate();

		AdvancedRoomListFragment listFragment = new AdvancedRoomListFragment(thisBuilding);
		roomListFragment = (RoomListFragmentInterface) listFragment;
		FragmentTransaction transaction = getSupportFragmentManager().beginTransaction().replace(R.id.mainView, listFragment);
		transaction.commit();
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);

		outState.putParcelable("BUILDING", thisBuilding);

		if (activeFragment != null) {
			try {
				getSupportFragmentManager().putFragment(outState, "ACTIVE_FRAGMENT", activeFragment);

				if (activeFragment instanceof AdvancedNewRoomFragment) {
					outState.putLong("ROOM_ID", ((AdvancedNewRoomFragment) activeFragment).getRoomId());
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

//	@Override
//	protected void onStop() {
//		super.onStop();
//
//	}

	@Override
	protected void onPause() {
		super.onPause();

		writeDateFile();
	}
	
	protected Building readFile() {
		Log.d("Advanced A/C Calculator", "Retrieving building...");

		Building tempBuilding = null;
		boolean fileOpen[] = { false, false };
		FileInputStream fis = null;
		ObjectInputStream in = null;
		try {

			fis = openFileInput("building.sav");
			fileOpen[0] = true;
			in = new ObjectInputStream(fis);
			fileOpen[1] = true;

			while (true) {
				tempBuilding = (Building) in.readObject();
				if (tempBuilding != null) {
					break;
				}
			}

		} catch (EOFException eofe) {
			Log.d("Advanced A/C Calculator", "Successfully reached end of data file");
		} catch (FileNotFoundException fnfe) {
			Log.e("Advanced A/C Calculator", "Data file not found");
		} catch (IOException ioe) {
			Log.e("Advanced A/C Calculator", "Error reading from data file");
		} catch (ClassNotFoundException cnfe) {
			Log.e("Advanced A/C Calculator", "Class Not Found Exception reading data file");
		} finally {
			try {
				if (fileOpen[0]) {
					in.close();
				}
				if (fileOpen[1]) {
					fis.close();
				}
			} catch (IOException ioe) {
				Log.e("Advanced A/C Calculator", "I/O error closing file");
			}
		}

		if (tempBuilding != null) {
			return tempBuilding;
		}

		return new Building();
	}

	protected void writeDateFile() {

		Log.d("Advanced A/C Calculator", "Writing to temp file...");
		boolean[] fileOpen = new boolean[2];
		fileOpen[0] = false;
		fileOpen[1] = false;
		FileOutputStream fos = null;
		ObjectOutputStream out = null;
		try {
			fos = openFileOutput("savefile.tmp", MODE_PRIVATE);
			fileOpen[0] = true;
			out = new ObjectOutputStream(fos);
			fileOpen[1] = true;


			out.writeObject(thisBuilding);
			out.flush();

		} catch (IOException ioe) {
			Log.e("Advanced A/C Calculator", "Error writing data to file");
			ioe.printStackTrace();
		} finally {
			try {
				if (fileOpen[0]) {
					out.close();
				}
				if (fileOpen[1]) {
					fos.close();
				}
			} catch (IOException ioe) {
				Log.e("Advanced A/C Calculator", "I/O error closing file");
			}
		}

		File tempFile = new File(getFilesDir(), "savefile.tmp");
		File oldSaveFile = new File(getFilesDir(), "building.sav");
		oldSaveFile.delete();
		tempFile.renameTo(oldSaveFile);
		Log.d("Advanced A/C Calculator", "Temp file contents successfully saved to data file");
	}

	public void displayLocaleDialog(Context context, String[] newSearchString) {
		DialogFragment loadLocale = new LocaleDialog(context, newSearchString);
		loadLocale.show(getSupportFragmentManager(), "Dialog");
	}
	
	public void displayInfoDialog(Context context, int type, String showAgainTag) {
		
		SharedPreferences prefs = getSharedPreferences("config.dat", Context.MODE_PRIVATE);
		DialogFragment infoDialog = null;
		
		if (showAgainTag != null) {
			if (prefs.getBoolean(showAgainTag, true)) {
				infoDialog = new InformationDialog(context, type, showAgainTag);
			} else {
				return;
			}
		} else {
			infoDialog = new InformationDialog(context, type, null);
		}
		
		infoDialog.show(getSupportFragmentManager(), "Dialog");
	}

	public String getNumberString(int number, int places) {
		String placeString = "";

		for (int i = 0; i < places; i++) {
			placeString = placeString + "#";
		}

		df.applyLocalizedPattern("#" + dfs.getDecimalSeparator() + placeString);
		return df.format(number);
	}

	public String getNumberString(double number, int places) {

		String placeString = "";

		for (int i = 0; i < places; i++) {
			placeString = placeString + "#";
		}

		df.applyLocalizedPattern("#" + dfs.getDecimalSeparator() + placeString);
		return df.format(number);
	}

	public double getDecimalFromString(String str) {
		try {
			return nf.parse(str).doubleValue();
		} catch (ParseException e) {
			e.printStackTrace();
			return 0;
		}
	}

	public int getIntFromString(String str) {
		try {
			return nf.parse(str).intValue();
		} catch (ParseException e) {
			e.printStackTrace();
			return 0;
		}
	}
}
